/**
 * @file UI.c
 * @brief 底盘UI显示模块，实现裁判系统图像绘制功能
 *        支持线、矩形、圆等基础图形及字符串、数值显示
 * @author WeiFan Qiu (qiuweifan0523@faxmail.com)
 * @version 1.0
 * @date 2025-08-08
 *
 * @copyright Copyright (c) 2025  邱伟凡
 *           参考吉林大学动态ui库
 * @par 修改日志:
 *   - 2025-08-08: 初始版本创建
 *
 * @bug 待解决问题:
 *   - 图形刷新频率与裁判系统同步优化
 *   - 字符串显示长度截断逻辑完善
 *   - 貌似是会发送出去的数据错位，待检查
 */
/*引用层*/
#include "QWF_Ctrl.h"  	//因为要引用的太多了，直接用ctrl文件
#include "cmsis_os.h"	//互斥锁相关的
/*裁判系统crc*/
void Append_CRC8_Check_Sum(unsigned char* data, unsigned int length);
void Append_CRC16_Check_Sum(uint8_t* data, uint32_t length);
/*******************************通用*********************************/
/*变量层*/
/**
 * @brief UI系统全局实例，存储当前所有图形对象的元数据
 */
static my_ui_id My_Ui_Id;
my_ui_id* my_ui = &My_Ui_Id;
/**
 * @brief UI图形数据存储数组（最大支持ui_data_num个图形）
 */
static UI_Data_t ui_data[ui_data_num];  // 图像列表
/**
 * @brief 裁判系统图像数据发送缓冲区（最大120字节）
 */
static uint8_t ui_tx_buffer[120];  // 发送缓冲区（协议头+7个图形数据）
static uint32_t auto_ui_name = 1;  // 自增id用于给裁判系统索引，但只取低3byte
static uint32_t jluiScanOffset = 0;
/*发送函数串口*/
void Send_Data_To_USART(UART_HandleTypeDef* huart,uint8_t* data,uint16_t data_Byte);
/**************互斥锁，防止数据修改一半被打断，每次创造/修改ui图像时都要先上锁，做完再开锁(暂时没用)************************/
// static void* ui_list_mutex =
// (void*)1;//对象列表互斥锁,初始化为1锁死，ui初始化完成后再变成设置的
extern osMutexId UI_MutexHandle;
/*设置互斥锁*/
// void JLUI_SetMutexObject(void* mutex) { ui_list_mutex = mutex; }
/*上锁*/
_Bool QWF_Lock_Freertos(void* mutex) {
    return xSemaphoreTake((SemaphoreHandle_t)mutex, 10) == pdTRUE;
    //    return 1;
}
/*获取发送包对应信息*/
#define get_tx_head() (ui_tx_head_t*)(ui_tx_buffer)
#define get_tx_ui_obj(index)                              \
    (ui_tx_ui_obj*)(ui_tx_buffer + sizeof(ui_tx_head_t) + index * sizeof(ui_tx_ui_obj))
#define get_tx_ui_char_data() \
    (char*)(ui_tx_buffer + sizeof(ui_tx_head_t) + sizeof(ui_tx_ui_obj))
/******************************* 字符串相关 **********************************/
/*发送的字符串*/
static char C_Mode[30] = {"C:Normal"};       // 底盘
static char G_Mode[30] = {"G:Vision"};       // 云台
static char F_Mode[30] = {"F:Communicate"};  // 发弹机构
static char V_Mode[30] = {"V:drop::USE"};    // 视觉
static char Power[30] = {"Power:USE "};
// static char w_top[30]	 ={"W_Top:Change"};//小陀螺转速
// static char v_fire[30]	 ={"V_Fire:Loop"};//小陀螺转速
//  标志位，为true时表示下一次要更新的图形项为字符串。
static bool next_updata_string = false;
// 当下一次要更新的图形项为字符串时，此值代表着字符串对象在列表中的索引。
static uint32_t string_index = 0;
#define lock_try(...) \
//    do                                          \
//    {                                           \
//        if (!QWF_Lock_Freertos(ui_list_mutex)) \
//        {                                       \
//            return __VA_ARGS__;                 \
//        }                                       \
//    } while (0)
/*解锁*/
void QWF_UnLock_Freertos(void* mutex) {
    xSemaphoreGive((SemaphoreHandle_t)mutex);
}
#define unlock() \
//    do                                       \
//    {                                        \
//        QWF_UnLock_Freertos(ui_list_mutex); \
//    } while (0)
/**************************** ui操作
 * *******************************************************/
/*************************** 创造ui图像
 * **************************************************/
/*创生并初始化新的ui图像,后面的函数会不断调用这个函数生成新的图像，故用static*/
/**
 * @brief 创建并初始化新的UI图形对象
 * @details 遍历ui_data数组寻找空闲槽位，初始化元数据及默认参数
 * @return 新图形对象索引（-1表示无空闲空间）
 */
static int32_t create_init_ui(void) {
    for (int32_t i = 0; i < ui_data_num; i++) {
        if (!ui_data[i].meta.valid) {
            // 初始化元数据，保证下次Tick时能更新上去
            ui_data[i].meta.valid = true;
            ui_data[i].meta.deleted = false;
            ui_data[i].meta.dirty = false;
            ui_data[i].meta.dirtyVisibility = true;  // 让后面能扫到它的更新
            ui_data[i].meta.visible = true;
            // 初始化索引
            memcpy(ui_data[i].name, (void*)&auto_ui_name, 3);
            // 初始化所有细节字段为0
            ui_data[i].word1.data = 0;
            ui_data[i].word2.data = 0;
            ui_data[i].word3.data = 0;
            // 自增ID.data增加
            auto_ui_name++;
            return i;
        }
    }
    return -1;
}
/*线*/
/**
 * @brief 创建直线图形
 * @param[in] width 线宽（像素）
 * @param[in] color 颜色（RGB565格式）
 * @param[in] layer 显示图层（数值越大越上层）
 * @param[in] x1 起点X坐标
 * @param[in] y1 起点Y坐标
 * @param[in] x2 终点X坐标
 * @param[in] y2 终点Y坐标
 * @return 新图形ID（UiNoMoreSpace表示无空间）
 */
ui_id ui_create_line(int width,
                     ui_color color,
                     int layer,
                     int x1,
                     int y1,
                     int x2,
                     int y2) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiLine;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x1;
    ui_data[new_id].word2.pack.y = y1;
    ui_data[new_id].word3.pack_line.x2 = x2;
    ui_data[new_id].word3.pack_line.y2 = y2;

    unlock();
    return new_id;
}
/*矩形*/
/**
 * @brief 创建矩形图形
 * @param[in] width 边框线宽（像素，0表示填充）
 * @param[in] color 颜色（RGB565格式）
 * @param[in] layer 显示图层
 * @param[in] x1 左上角X坐标
 * @param[in] y1 左上角Y坐标
 * @param[in] x2 右下角X坐标
 * @param[in] y2 右下角Y坐标
 * @return 新图形ID
 */
ui_id ui_create_rect(int width,
                     ui_color color,
                     int layer,
                     int x1,
                     int y1,
                     int x2,
                     int y2) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiRect;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x1;
    ui_data[new_id].word2.pack.y = y1;
    ui_data[new_id].word3.pack_rect.x2 = x2;
    ui_data[new_id].word3.pack_rect.y2 = y2;

    unlock();
    return new_id;
}
/*圆*/
/**
 * @brief 创建圆形图形
 * @param[in] width 边框线宽（像素，0表示填充）
 * @param[in] color 颜色（RGB565格式）
 * @param[in] layer 显示图层
 * @param[in] x 圆心X坐标
 * @param[in] y 圆心Y坐标
 * @param[in] r 半径（像素）
 * @return 新图形ID
 */
ui_id ui_create_circle(int width,
                       ui_color color,
                       int layer,
                       int x,
                       int y,
                       int r) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiCircle;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x;
    ui_data[new_id].word2.pack.y = y;
    ui_data[new_id].word3.pack_circle.radius = r;

    unlock();
    return new_id;
}
/*椭圆*/
/**
 * @brief 创建椭圆图形
 * @param[in] width 边框线宽（像素，0表示填充）
 * @param[in] color 颜色（RGB565格式）
 * @param[in] layer 显示图层
 * @param[in] x 椭圆中心X坐标
 * @param[in] y 椭圆中心Y坐标
 * @param[in] xSemiaxis X轴半轴长度
 * @param[in] ySemiaxis Y轴半轴长度
 * @return 新图形ID
 */
ui_id ui_create_ellipse(int width,
                        ui_color color,
                        int layer,
                        int x,
                        int y,
                        int xSemiaxis,
                        int ySemiaxis) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiEllipse;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x;
    ui_data[new_id].word2.pack.y = y;
    ui_data[new_id].word3.pack_ellipse.xSemiaxis = xSemiaxis;
    ui_data[new_id].word3.pack_ellipse.ySemiaxis = ySemiaxis;

    unlock();
    return new_id;
}
/*圆弧*/
ui_id ui_create_arc(int width,
                    ui_color color,
                    int layer,
                    int x,
                    int y,
                    int xSemiaxis,
                    int ySemiaxis,
                    int startAngle,
                    int endAngle) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiArc;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x;
    ui_data[new_id].word2.pack.y = y;
    ui_data[new_id].word3.pack_ellipse.xSemiaxis = xSemiaxis;
    ui_data[new_id].word3.pack_ellipse.ySemiaxis = ySemiaxis;
    ui_data[new_id].word1.pack.detailA = startAngle;
    ui_data[new_id].word1.pack.detailB = endAngle;

    unlock();
    return new_id;
}
/*单浮点+整形 */
ui_id ui_create_float_int(int width,
                          ui_color color,
                          int layer,
                          int x,
                          int y,
                          int fontSize,
                          int value) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiFloat;
    ui_data[new_id].word1.pack.detailA = fontSize;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x;
    ui_data[new_id].word2.pack.y = y;
    ui_data[new_id].word3.float_val = value;
    unlock();
    return new_id;
}
/*单浮点 */
ui_id ui_create_float_only(int width,
                           ui_color color,
                           int layer,
                           int x,
                           int y,
                           int fontSize,
                           float value) {
    return ui_create_float_int(width, color, layer, x, y, fontSize,
                               (uint32_t)(value * 1000));
}
/**整形 */
ui_id ui_create_int_only(int width,
                         ui_color color,
                         int layer,
                         int x,
                         int y,
                         int fontSize,
                         int value) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiInt;
    ui_data[new_id].word1.pack.detailA = fontSize;
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x;
    ui_data[new_id].word2.pack.y = y;
    ui_data[new_id].word3.int_val = value;
    unlock();
    return new_id;
}
/*字符串*/
ui_id ui_create_string(int width,
                       ui_color color,
                       int layer,
                       int x,
                       int y,
                       int fontSize,
                       const char* str) {
    lock_try(ui_err_id);

    int32_t new_id = create_init_ui();
    if (new_id < 0) {
        return UiNoMoreSpace;
    }
    ui_data[new_id].word1.pack.color = color;
    ui_data[new_id].word1.pack.layer = layer;
    ui_data[new_id].word1.pack.type = UiStr;
    ui_data[new_id].word1.pack.detailA = fontSize;
    ui_data[new_id].word1.pack.detailB = QWF_Min(30u, strlen(str));
    ui_data[new_id].word2.pack.width = width;
    ui_data[new_id].word2.pack.x = x;
    ui_data[new_id].word2.pack.y = y;
    ui_data[new_id].word3.str_val = str;

    unlock();
    return new_id;
}
/***************************** 修改ui图像 *************************/
/*修改可见性 */
/**
 * @brief 设置图形可见性
 * @param[in] id 图形ID
 * @param[in] visible true-显示，false-隐藏
 * @note 标记dirtyVisibility以触发下次发送更新
 */
void ui_set_visible(ui_id id, bool visible) {
    if (ui_data[id].meta.visible == visible) {
        return;
    }

    lock_try();

    ui_data[id].meta.dirtyVisibility = true;  // 特殊处理，可见性修改
    ui_data[id].meta.visible = visible;

    unlock();
}
/**
 * @brief 修改图形颜色
 * @param[in] id 图形ID
 * @param[in] color 新颜色值（RGB565格式）
 * @note 标记dirty以触发下次发送更新
 */
void ui_set_color(ui_id id, ui_color color) {
    if (ui_data[id].word1.pack.color == color) {
        return;
    }

    lock_try();

    ui_data[id].meta.dirty = true;
    ui_data[id].word1.pack.color = color;
    unlock();
}
/**
 * @brief 修改图形线宽
 * @param[in] id 图形ID
 * @param[in] width 新线宽（像素）
 * @note 仅对支持线宽的图形类型有效（如线、矩形边框等）
 */
void ui_set_width(ui_id id, int width) {
    if (ui_data[id].word2.pack.width == width) {
        return;
    }

    lock_try();

    ui_data[id].meta.dirty = true;
    ui_data[id].word2.pack.width = width;
    unlock();
}
/**
 * @brief 设置字符串/数值显示字体大小
 * @param[in] id 图形ID（仅字符串/数值类型有效）
 * @param[in] size 字体大小（像素）
 */
void ui_set_font_size(ui_id id, int size) {
    if (ui_data[id].word1.pack.detailA == size) {
        return;
    }

    lock_try();

    ui_data[id].word1.pack.detailA = size;
    ui_data[id].meta.dirty = true;
    unlock();
}
/*标志着字符串改变*/
void ui_set_string_change(ui_id id) {
    lock_try();

    ui_data[id].word1.pack.detailB =
        QWF_Min(strlen(ui_data[id].word3.str_val), 30u);
    ui_data[id].meta.dirty = true;
    unlock();
}
void ui_set_xy1(ui_id id, int x, int y) {
    if (ui_data[id].word2.pack.x == x && ui_data[id].word2.pack.y == y) {
        return;
    }

    lock_try();

    ui_data[id].word2.pack.x = x;
    ui_data[id].word2.pack.y = y;
    ui_data[id].meta.dirty = true;
    unlock();
}
void ui_set_xy2(ui_id id, int x, int y) {
    if (ui_data[id].word3.pack_line.x2 == x &&
        ui_data[id].word3.pack_line.y2 == y) {
        return;
    }

    lock_try();

    ui_data[id].word3.pack_line.x2 = x;
    ui_data[id].word3.pack_line.y2 = y;
    ui_data[id].meta.dirty = true;
    unlock();
}
void ui_set_r(ui_id id, int r) {
    if (ui_data[id].word3.pack_circle.radius == r) {
        return;
    }

    lock_try();

    ui_data[id].word3.pack_circle.radius = r;
    ui_data[id].meta.dirty = true;
    unlock();
}
void ui_set_semiaxis(ui_id id, int x_semiaxis, int y_semiaxis) {
    if (ui_data[id].word3.pack_ellipse.xSemiaxis == x_semiaxis &&
        ui_data[id].word3.pack_ellipse.ySemiaxis == y_semiaxis) {
        return;
    }

    lock_try();
    ui_data[id].word3.pack_ellipse.xSemiaxis = x_semiaxis;
    ui_data[id].word3.pack_ellipse.ySemiaxis = y_semiaxis;
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_start_angle(ui_id id, int start_angle) {
    if (ui_data[id].word1.pack.detailA == start_angle) {
        return;
    }

    lock_try();
    ui_data[id].word1.pack.detailA = start_angle;
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_end_angle(ui_id id, int end_angle) {
    if (ui_data[id].word1.pack.detailB == end_angle) {
        return;
    }

    lock_try();
    ui_data[id].word1.pack.detailB = end_angle;
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_float_only(ui_id id, float value) {
    if (ui_data[id].word3.float_val == value) {
        return;
    }

    lock_try();
    ui_data[id].word3.float_val = value * 1000;
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_float_int(ui_id id, int value) {
    if (ui_data[id].word3.float_val == value) {
        return;
    }

    lock_try();
    ui_data[id].word3.float_val = value;
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_int_only(ui_id id, int value) {
    if (ui_data[id].word3.int_val == value) {
        return;
    }

    lock_try();
    ui_data[id].word3.int_val = value;
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_str(ui_id id, const char* str) {
    if (strcmp(ui_data[id].word3.str_val, str) == 0) {
        return;
    }

    lock_try();
    ui_data[id].word3.str_val = str;
    ui_data[id].word1.pack.detailB = QWF_Min(strlen(str), 30u);
    ui_data[id].meta.dirty = true;

    unlock();
}
void ui_set_str_len(ui_id id, const char* str, int length) {
    if ((strcmp(ui_data[id].word3.str_val, str) == 0) &&
        ui_data[id].word1.pack.detailB == QWF_Min(length, 30u)) {
        return;
    }

    lock_try();
    ui_data[id].word3.str_val = str;
    ui_data[id].word1.pack.detailB = QWF_Min(length, 30u);
    ui_data[id].meta.dirty = true;

    unlock();
}
/**************************** 发送ui图像 **********************/
size_t itemsProcessed = 0;  // 裁判系统处理的图像数（最多7个）
/**
 * @brief 通过串口DMA发送UI数据到裁判系统
 * @param[in] data 待发送数据缓冲区
 * @param[in] len 数据长度（字节）
 * @note 使用USART1发送，需确保裁判系统已连接
 */
static void ui_dma_tx(uint8_t* data, uint32_t len) {
    Send_Data_To_USART(&huart1, data, len);
    //   osDelay(5);
}
/**
 * @brief 向发送缓冲区写入图形对象的操作信息
 *
 * 该函数将指定图形对象的信息写入到发送缓冲区的指定位置，并设置操作类型。
 *
 * @param txBufferIndex 发送缓冲区的索引，指示要写入的位置
 * @param objectListIndex 图形对象列表的索引，指示要写入的图形对象
 * @param act 操作类型，如添加、修改、删除等
 */
static void JLUI_Internal_WriteTxBufferObjectOperation(
    uint32_t txBufferIndex,
    uint32_t objectListIndex,
    ui_act act)  // 写入缓冲区
{
    // 获取图形对象列表中指定索引的图形对象
    UI_Data_t* obj = &ui_data[objectListIndex];
    // 获取发送缓冲区中指定索引的对象
    ui_tx_ui_obj* bufferObj = get_tx_ui_obj(txBufferIndex);
    // 填充
    bufferObj->detailDword1.data = obj->word1.data;
    bufferObj->detailDword2 = obj->word2.data;
    bufferObj->detailDword3 = obj->word3.data;
    memcpy((void*)&(bufferObj->name), (void*)&(obj->name), 3);  // 名字
    // 设置操作类型
    bufferObj->detailDword1.detailDword1Internal.operation = act;
}
/**
 * @brief 向裁判系统发送指定索引的字符串对象
 *
 * 此函数用于将指定索引的字符串对象发送到裁判系统，可指定操作类型（如添加、修改等）。
 *
 * @param index 字符串对象在 ui_data 数组中的索引
 * @param act 对字符串对象的操作类型，如添加、修改等
 */
static void JLUI_Internal_TransmitStringObject(uint32_t index,
                                               ui_act act) {  // 发送字符串
    // 获取指定索引的字符串对象
    UI_Data_t* strObj = &ui_data[index];
    // 获取发送缓冲区头部
    ui_tx_head_t* header = get_tx_head();
    header->DataLength =
        51;  // (6)+15+30/ 数据长度：6字节头部 + 15字节元数据 + 30字节字符串
    Append_CRC8_Check_Sum((uint8_t*)(header), 5);

    header->ContentId =
        INTERACT_ID_draw_char_graphic;  // 设置内容ID为绘制字符图形
    // 获取发送缓冲区中的字符串元数据对象
    ui_tx_ui_obj* stringMeta = get_tx_ui_obj(0);
    // 填充字符串到缓冲区
    stringMeta->detailDword1.data = strObj->word1.data;
    stringMeta->detailDword2 = strObj->word2.data;
    stringMeta->detailDword3 = strObj->word3.data;
    memcpy((void*)&(stringMeta->name), (void*)&(strObj->name), 3);  // 名字
    stringMeta->detailDword1.detailDword1Internal.operation = act;
    // 获取字符串缓冲区并初始化
    char* stringBuffer = get_tx_ui_char_data();
    memset(stringBuffer, 0, 30);
    // 填入所需的字符串
    strncpy(stringBuffer, strObj->word3.str_val,
            QWF_Min((uint32_t)(strObj->word1.pack.detailB), 30u));
    // 计算并添加CRC16校验
    Append_CRC16_Check_Sum(ui_tx_buffer, 60);  // (5+2+6)+15+30+2

    ui_dma_tx(ui_tx_buffer, 60);
}

/**
 * @brief 向裁判系统发送除字符串外的其他图形对象
 *
 * 此函数根据需要发送的图形对象数量，选择合适的数据包格式和内容ID，
 * 将图形对象信息写入发送缓冲区，并进行CRC校验，最后通过DMA发送数据。
 *
 * @param count 需要发送的图形对象数量
 */
static void JLUI_Internal_TransmitOtherObjects(size_t count) {  // 发送其余的
    /**图像个数 */
    static const uint8_t elementCountInPacketTable[] = {0, 1, 2, 5, 5, 5, 7, 7};
    /**对应命令 */
    static const uint16_t contentIdTable[] =
        /*不绘制 	1个
           2个
           3个->5个（向上取整）		4个->5个（向上取整）
           5个
           6个->7个（向上取整）			7个
         */
        {0,
         INTERACT_ID_draw_one_graphic,
         INTERACT_ID_draw_two_graphic,
         INTERACT_ID_draw_five_graphic,
         INTERACT_ID_draw_five_graphic,
         INTERACT_ID_draw_five_graphic,
         INTERACT_ID_draw_seven_graphic,
         INTERACT_ID_draw_seven_graphic};
    // 根据需要发送的图形对象数量，从 elementCountInPacketTable
    // 中获取每个数据包中图形元素的数量
    uint32_t elementCountInPacket = elementCountInPacketTable[count];
    // 获取发送缓冲区的头部指针
    ui_tx_head_t* header = get_tx_head();
    // 设置数据包的数据长度，包括头部和每个图形元素的元数据长度
    header->DataLength =
        6 + elementCountInPacket * 15;  // (2+2+2)+15*elementCountInPacket
    // 计算并添加CRC8校验和到头部数据
    Append_CRC8_Check_Sum((uint8_t*)(header), 5);
    // 根据需要发送的图形对象数量，从 contentIdTable 中获取对应的内容ID
    header->ContentId = contentIdTable[count];
    // 将没有用到的图形的操作码清除，避免无效数据干扰
    for (size_t i = count; i < elementCountInPacket;
         i++) {  // 获取发送缓冲区中指定索引的图形对象元数据指针
        ui_tx_ui_obj* bufferObj = get_tx_ui_obj(i);
        // 将操作码设置为无操作，即不进行任何操作（在发送函数里会识别类型并且选择操作）
        bufferObj->detailDword1.detailDword1Internal.operation = UiOpNoop;
    }
    // 计算并添加CRC16校验和到整个数据包
    Append_CRC16_Check_Sum(ui_tx_buffer, 13 + elementCountInPacket * 15 + 2);

    ui_dma_tx(ui_tx_buffer, 13 + elementCountInPacket * 15 + 2);
}

static void JLUI_Internal_LoopIncrement(uint32_t* x) {
    *x = (*x + 1) % ui_data_num;
}
typedef bool (*loop__call_back)(uint32_t i, UI_Data_t* data);  // 回调函数
bool iterStrObj(uint32_t i, UI_Data_t* data) {                 // 字符回调
    if (data->word1.pack.type == UiStr) {
        string_index = i;
        next_updata_string = true;
        return false;
    }
    return true;
}
bool iterObj(uint32_t i, UI_Data_t* data) {  // 其余回调
    // 递增一次扫描起始点
    JLUI_Internal_LoopIncrement(&jluiScanOffset);
    // 跳过未用到（无效）的项
    if (!data->meta.valid) {
        return true;
    }
    // 跳过没有任何脏标记的项
    if (!data->meta.dirty && !data->meta.dirtyVisibility &&
        !data->meta.deleted) {
        return true;
    }
    // 处理脏标记
    if (data->meta.deleted) {
        // 如果已经标记为删除，添加删除操作，并去除有效位
        data->meta.valid = false;
        JLUI_Internal_WriteTxBufferObjectOperation(itemsProcessed, i,
                                                   UiOpDelete);
        itemsProcessed++;
    } else if (
        data->meta
            .dirtyVisibility) {  // 否则，如果可见性改变，则添加删除/添加操作
        if (data->meta.visible)  // 可见
        {
            if (data->word1.pack.type == UiStr) {  // 字符串显示必须单独处理
                if (!next_updata_string) {  // 下一次不是字符串，设置下一次更新这个字符串
                    next_updata_string = true;
                    string_index = i;
                }
            } else {  // 简单图形项的设置
                // 创建
                data->meta.dirtyVisibility = false;
                JLUI_Internal_WriteTxBufferObjectOperation(itemsProcessed, i,
                                                           UiOpAdd);
                itemsProcessed++;
            }
        } else {  // 删除操作所有对象都是统一的
            // 删除
            data->meta.dirtyVisibility = false;
            JLUI_Internal_WriteTxBufferObjectOperation(itemsProcessed, i,
                                                       UiOpDelete);
            itemsProcessed++;
        }
    } else if (data->meta.dirty) {
        // 对于字符串，设置标志位，下次Tick时只更新一个字符串
        // 注意不要在已经设置了字符串更新标志位的情况下再次记录，会丢失上次的记录
        if (data->word1.pack.type == UiStr &&
            !next_updata_string) {  // 下一次不是字符串，设置下一次更新这个字符串
            next_updata_string = true;
            string_index = i;
        } else {
            // 否则，如果有脏标记，则添加修改操作
            data->meta.dirty = false;
            JLUI_Internal_WriteTxBufferObjectOperation(itemsProcessed, i,
                                                       UiOpModify);
            itemsProcessed++;
        }
    } else {
        // 不应该发生
        return false;
    }
    // 处理完这个脏图形后立即检测缓冲区是否已满，如果满，退出循环
    if (itemsProcessed >= 7) {  // 裁判系统可发送数据满了
        return false;
    }
    return true;
}

static void JLUI_Internal_LoopScanObjectList(uint32_t fromIndex,   ///< 包含
                                             uint32_t untilIndex,  ///< 不包含
                                             loop__call_back callback) {
    // 上界小于下界就默认是从末尾环绕回开头
    uint32_t upperBound =
        ((untilIndex <= fromIndex) ? (untilIndex + ui_data_num) : untilIndex);
    for (size_t i = fromIndex; i < upperBound; i++) {
        // 回调返回false时，跳出循环
        if (!callback(i % ui_data_num, &ui_data[i % ui_data_num])) {
            break;
        }
    }
}
/**
 * @brief 设置发送者和接收者的 ID
 *
 * 该函数用于设置发送缓冲区头部的发送者和接收者 ID，同时设置起始帧标志和序列号。
 *
 * @param senderId 发送者的 ID
 * @param receiverId 接收者的 ID
 */
void JLUI_SetSenderReceiverId(uint16_t senderId, uint16_t receiverId) {
    // 获取发送缓冲区头部指针
    ui_tx_head_t* header = get_tx_head();
    // 设置起始帧标志
    header->SOF = 0xA5;
    // 设置发送数据包的序列号为 0
    header->Seq = 0;
    // 设置发送者的 ID
    header->SenderId = senderId;
    // 设置接收者的 ID
    header->ReceiverId = receiverId;
    // 设置命令 ID 为 机器人交互式据
    header->CommandId = custom_info_id;
    memset(ui_data, 0, sizeof(ui_data));
}
/**
 * @brief 每 10Hz 执行一次的 UI 更新任务
 *
 * 该函数用于定期执行 UI 更新操作，会尝试对操作加锁，以确保线程安全。
 * 在加锁成功后，会进行一系列的 UI 数据处理和发送操作。
 */
void JLUI_10HzTick() {
    lock_try();
    static bool alreadySentStringOnce = false;
RestartForStringProcessing:
    alreadySentStringOnce = false;
    if (next_updata_string) {  // 要求更新字符串
        // 找到字符串
        // if (string_index >= ui_data_num)
        // {
        //     // 字符串索引超出范围，直接退出
        //     unlock();
        //     return;
        // }
        UI_Data_t* obj = &ui_data[string_index];
        obj->meta.dirty = false;
        alreadySentStringOnce = true;
        if (obj->meta.dirtyVisibility && obj->meta.visible) {
            // 创建字符串
            obj->meta.dirtyVisibility = false;
            JLUI_Internal_TransmitStringObject(string_index, UiOpAdd);
        } else {
            // 修改字符串
            JLUI_Internal_TransmitStringObject(string_index, UiOpModify);
        }
        // 前移一个图形元素
        JLUI_Internal_LoopIncrement(&string_index);
        next_updata_string = false;
        // 扫描剩下的字符串，找到字符串就恢复状态位
        JLUI_Internal_LoopScanObjectList(string_index, jluiScanOffset,
                                         iterStrObj);
    } else {  // 要求更新其他的
        // 扫描列表，查找需要更新的图形，至多7个
        itemsProcessed = 0;

        JLUI_Internal_LoopScanObjectList(jluiScanOffset, jluiScanOffset,
                                         iterObj);
        // 如果有需要更新的图形，发送数据
        if (itemsProcessed > 0) {
            JLUI_Internal_TransmitOtherObjects(itemsProcessed);
        } else if (itemsProcessed == 0 && next_updata_string &&
                   !alreadySentStringOnce) {
            // 如果没有处理简单图形项但是出现了需要处理的字符串，就跳到函数开头重新开始
            goto RestartForStringProcessing;
        }
    }
    // 解锁
    unlock();
}

/********************************** 删除ui图像**************************/
void ui_delete_only(
    ui_id id) {  // 删除特定id的图像(实际上就是把元数据的deleted项置1)
    lock_try();
    ui_data[id].meta.deleted = true;
    unlock();
}

void ui_delete_all(void) {  // 删除所有
    // TODO:
    // 可以直接用裁判系统的删除命令，但需要特殊数据包，暂未实现op
    lock_try();
    for (int id = 0; id < ui_data_num; id++) {
        ui_data[id].meta.deleted = true;
    }
    unlock();
}
ui_cmd_t UI_CMD = {.create = {.line = ui_create_line,
                              .rect = ui_create_rect,
                              .circle = ui_create_circle,
                              .ellipse = ui_create_ellipse,
                              .arc = ui_create_arc,
                              .string = ui_create_string,
                              .float_only = ui_create_float_only,
                              .float_int = ui_create_float_int,
                              .int_only = ui_create_int_only},
                   .set = {.visible = ui_set_visible,
                           .color = ui_set_color,
                           .width = ui_set_width,
                           .font_size = ui_set_font_size,
                           .xy1 = ui_set_xy1,
                           .xy2 = ui_set_xy2,
                           .r = ui_set_r,
                           .semiaxis = ui_set_semiaxis,
                           .start_angle = ui_set_start_angle,
                           .end_angle = ui_set_end_angle,
                           .float_only = ui_set_float_only,
                           .float_int = ui_set_float_int,
                           .int_only = ui_set_int_only,
                           .str = ui_set_str,
                           .str_len = ui_set_str_len},
                   .delet = {.only = ui_delete_only, .all = ui_delete_all}};
ui_cmd_t* ui_cmd = &UI_CMD;
uint16_t ui_init_flag = 0;
int32_t persent = 0;
void ui_task(void const* argument) {
    while (1) {
        //       JLUI_SetMutexObject((void*)UI_MutexHandle);
        switch (ui_init_flag) {
            case 0: {  // 初始化ui系统
                //			judge->robot_status.robot_id = 0x001;
                //judge->self_client = 0x101;
                if (judge->robot_status.robot_id != 0 &&
                    judge->self_client != 0) {
                    JLUI_SetSenderReceiverId(judge->robot_status.robot_id,
                                             judge->self_client);
                    //                 JLUI_SetMutexObject((void*)UI_MutexHandle);
                    ui_init_flag = 1;
                }
            } break;
            case 1: {  // 初始化图形
                {      // 车体姿态
                    my_ui->my_car.Gimbal = ui_cmd->create.line(
                        2, UiGreen, 0, 559, 736, 559, 736 + 105);
                    my_ui->my_car.Board[1 - 1] =
                        ui_cmd->create.line(2, UiGreen, 0, 300, 300, 500, 500);
                    my_ui->my_car.Board[2 - 1] =
                        ui_cmd->create.line(2, UiGreen, 0, 300, 300, 500, 500);
                    my_ui->my_car.Board[3 - 1] =
                        ui_cmd->create.line(2, UiGreen, 0, 300, 300, 500, 500);
                    my_ui->my_car.Board[4 - 1] =
                        ui_cmd->create.line(2, UiGreen, 0, 300, 300, 500, 500);
                }
                {  // 发射
                    my_ui->fire.sight =
                        ui_cmd->create.circle(3, UiGreen, 0, 960, 450, 20);
                    my_ui->fire.scope =
                        ui_cmd->create.rect(3, UiGreen, 0, 1175, 650, 757, 351);
                    my_ui->fire.vision_distance = ui_cmd->create.int_only(
                        3, UiGreen, 1, 1362, 616, 20, 0);
                }
                {  // 超电
                    // my_ui->super_elec.now=ui_cmd->create.arc
                    // (10,UiGreen,1,1164,543,197,301,0,180);
                    // my_ui->super_elec.max=ui_cmd->create.arc
                    // (15,UiBlack,0,1164,543,197,301,0,180);
                    my_ui->super_elec.num = ui_cmd->create.int_only(
                        4, UiGreen, 1, 1400, 473, 20, persent);
                }
                //		{//血量
                //			if(my_team==blue){
                //			/*红色*/
                //		my_ui->HP[1-1][red]=ui_cmd->create.int_only
                //(4,UiGreen,0,759-120*0	,894
                //,20,judge->game_robot_HP.red_1_robot_HP);
                //		my_ui->HP[2-1][red]=ui_cmd->create.int_only
                //(4,UiGreen,0,759-120*1	,894
                //,20,judge->game_robot_HP.red_2_robot_HP);
                //		my_ui->HP[3-1][red]=ui_cmd->create.int_only
                //(4,UiGreen,0,759-120*2	,894
                //,20,judge->game_robot_HP.red_3_robot_HP);
                //		my_ui->HP[4-1][red]=ui_cmd->create.int_only
                //(4,UiGreen,0,759-120*3	,894
                //,20,judge->game_robot_HP.red_4_robot_HP);
                ////		my_ui->HP[5-1][red]=ui_cmd->create.int_only
                ///(4,UiGreen,0,759-120*4	,894
                ///,20,judge->game_robot_HP.red_5_robot_HP);
                //		my_ui->HP[6-1][red]=ui_cmd->create.int_only
                //(4,UiGreen,0,759-120*5	,894
                //,20,judge->game_robot_HP.red_7_robot_HP);
                ////		my_ui->HP[7-1][red]=ui_cmd->create.int_only
                ///(20,UiGreen,0,230		,1015
                ///,20,judge->game_robot_HP.red_7_robot_HP);
                //			}
                //			else if(my_team==red){
                //		/*蓝色*/
                //		my_ui->HP[1-1][blue]=ui_cmd->create.int_only
                //(4,UiGreen,0,1149+120*0,894
                //,20,judge->game_robot_HP.blue_1_robot_HP);
                //		my_ui->HP[2-1][blue]=ui_cmd->create.int_only
                //(4,UiGreen,0,1149+120*1,894
                //,20,judge->game_robot_HP.blue_2_robot_HP);
                //		my_ui->HP[3-1][blue]=ui_cmd->create.int_only
                //(4,UiGreen,0,1149+120*2,894
                //,20,judge->game_robot_HP.blue_3_robot_HP);
                //		my_ui->HP[4-1][blue]=ui_cmd->create.int_only
                //(4,UiGreen,0,1149+120*3,894
                //,20,judge->game_robot_HP.blue_4_robot_HP);
                ////		my_ui->HP[5-1][blue]=ui_cmd->create.int_only
                ///(4,UiGreen,0,1149+120*4,894
                ///,20,judge->game_robot_HP.blue_5_robot_HP);
                //		my_ui->HP[6-1][blue]=ui_cmd->create.int_only
                //(4,UiGreen,0,1149+120*5,894
                //,20,judge->game_robot_HP.blue_7_robot_HP);
                ////		my_ui->HP[7-1][blue]=ui_cmd->create.int_only
                ///(4,UiGreen,0,1675	    ,1015
                ///,20,judge->game_robot_HP.blue_outpost_HP);
                //			}
                //		}
                {  // 文本
                    my_ui->mode_txt.chassis = ui_cmd->create.string(
                        1, UiGreen, 2, 625, 750, 10, C_Mode);
                    my_ui->mode_txt.fire = ui_cmd->create.string(
                        1, UiGreen, 2, 577, 554, 10, F_Mode);
                    my_ui->mode_txt.vision = ui_cmd->create.string(
                        1, UiGreen, 2, 582, 490, 10, V_Mode);
                    my_ui->mode_txt.gimbal = ui_cmd->create.string(
                        1, UiGreen, 2, 600, 688, 10, G_Mode);
                    my_ui->mode_txt.power = ui_cmd->create.string(
                        1, UiGreen, 2, 1225, 600, 10, Power);
                }
                {  // 可修改文件

                    //		my_ui->change.w_top.text=ui_cmd->create.string(1,UiGreen,2,956-170,542+150,10,w_top);
                    //		my_ui->change.w_top.num=ui_cmd->create.int_only(1,UiGreen,2,956-200,542+95,10,chassia_top_w_now);
                    //		ui_cmd->set.visible(my_ui->change.w_top.text,0);
                    //		ui_cmd->set.visible(my_ui->change.w_top.num,0);
                    //
                    //		my_ui->change.v_fire.text=ui_cmd->create.string(1,UiGreen,2,956+170,542+150,10,v_fire);
                    //		my_ui->change.v_fire.num=ui_cmd->create.int_only(1,UiGreen,2,956+200,542+95,10,((Gimbal_Mode_Communicate_Struct_Type*)(communicate->head.mode->Data))->fire_max_i_want);
                    //		ui_cmd->set.visible(my_ui->change.v_fire.text,0);
                    //		ui_cmd->set.visible(my_ui->change.v_fire.num,0);
                }
                //
                //
                //

                ui_init_flag = 2;
            } break;
            case 2: {
                if (ctrl->KM[now].key.g)
                    ui_init_flag = 0;
                {  // 车体姿态
                    ui_cmd->set.xy1(
                        my_ui->my_car.Board[1 - 1],
                        559 +
                            50 *
                                arm_sin_f32(
                                    (chassis->part.yaw.motor.rx_meas.angle[0]) *
                                    PI / 4096),
                        736 +
                            50 *
                                arm_cos_f32(
                                    (chassis->part.yaw.motor.rx_meas.angle[0]) *
                                    PI / 4096));
                    ui_cmd->set.xy2(
                        my_ui->my_car.Board[1 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4) *
                                     PI / 4096));
                    ui_cmd->set.xy1(
                        my_ui->my_car.Board[2 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4) *
                                     PI / 4096));
                    ui_cmd->set.xy2(
                        my_ui->my_car.Board[2 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 2) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 2) *
                                     PI / 4096));
                    ui_cmd->set.xy1(
                        my_ui->my_car.Board[3 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 2) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 2) *
                                     PI / 4096));
                    ui_cmd->set.xy2(
                        my_ui->my_car.Board[3 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 3) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 3) *
                                     PI / 4096));
                    ui_cmd->set.xy1(
                        my_ui->my_car.Board[4 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 3) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 3) *
                                     PI / 4096));
                    ui_cmd->set.xy2(
                        my_ui->my_car.Board[4 - 1],
                        559 +
                            50 * arm_sin_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 4) *
                                     PI / 4096),
                        736 +
                            50 * arm_cos_f32(
                                     (chassis->part.yaw.motor.rx_meas.angle[0] +
                                      8192 / 4 * 4) *
                                     PI / 4096));
                }
                {  // 超电
                    //				if(!qwf_state->chassis.super_elec){//超电在线
                    //					ui_cmd->set.visible(my_ui->super_elec.now,1);
                    //					ui_cmd->set.visible(my_ui->super_elec.num,1);
                    //					ui_cmd->set.visible(my_ui->super_elec.max,1);

                    //					ui_cmd->set.start_angle(my_ui->super_elec.now,180+super_elec->rx.SuperCapEnergy*180.0f/2300);
                    ui_cmd->set.int_only(my_ui->super_elec.num, persent);

                    //					if(super_elec->rx.SuperCapEnergy/23>=75)
                    //							ui_cmd->set.color(my_ui->super_elec.now,UiGreen);
                    //					else
                    //if(super_elec->rx.SuperCapEnergy/23>=50)
                    //							ui_cmd->set.color(my_ui->super_elec.now,UiYellow);
                    //					else
                    //if(super_elec->rx.SuperCapEnergy/23>=25)
                    //							ui_cmd->set.color(my_ui->super_elec.now,UiOrange);
                    //					else
                    //							ui_cmd->set.color(my_ui->super_elec.now,UiMagenta);
                    //				}
                    //				else{
                    //					ui_cmd->set.visible(my_ui->super_elec.now,0);
                    //					ui_cmd->set.visible(my_ui->super_elec.num,0);
                    //					ui_cmd->set.visible(my_ui->super_elec.max,0);
                    //				}
                }
                {  // 发射模式
                    if (communicate->head.mode.data.str.shoot ==
                        fire_continuous)
                        ui_cmd->set.color(my_ui->fire.sight, UiYellow);
                    else if (communicate->head.mode.data.str.shoot == fire_once)
                        ui_cmd->set.color(my_ui->fire.sight, UiGreen);
                    else if (communicate->head.vision.data.str.fire)
                        ui_cmd->set.color(my_ui->fire.sight, UiCyan);
                    else
                        ui_cmd->set.color(my_ui->fire.sight, UiWhite);
                }
                {  // 视觉模式
                    if (communicate->head.vision.data.str.head_ok == 0)
                        ui_cmd->set.color(my_ui->fire.scope, UiMagenta);
                    else if (communicate->head.mode.data.str.vision ==
                             vision_mode_car)
                        ui_cmd->set.color(my_ui->fire.scope, UiGreen);
                    else if (communicate->head.mode.data.str.vision ==
                             vision_mode_small_flag)
                        ui_cmd->set.color(my_ui->fire.scope, UiBlack);
                    else if (communicate->head.mode.data.str.vision ==
                             vision_mode_big_flag)
                        ui_cmd->set.color(my_ui->fire.scope, UiWhite);
                }
                ui_cmd->set.int_only(
                    my_ui->fire.vision_distance,
                    communicate->head.vision.data.str.diatance);

                //			{//血量
                //				if(my_team==blue){
                //				/*红方*/
                //				/*数值*/
                //				ui_cmd->set.int_only(my_ui->HP[1-1][red],judge->game_robot_HP.red_1_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[2-1][red],judge->game_robot_HP.red_2_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[3-1][red],judge->game_robot_HP.red_3_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[4-1][red],judge->game_robot_HP.red_4_robot_HP);
                ////
                ///ui_cmd->set.int_only(my_ui->HP[5-1][red],judge->game_robot_HP.red_5_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[6-1][red],judge->game_robot_HP.red_7_robot_HP);
                ////
                ///ui_cmd->set.int_only(my_ui->HP[7-1][red],judge->game_robot_HP.red_outpost_HP);
                //				/*位置*/
                //				ui_cmd->set.xy1(my_ui->HP[1-1][red],759-120*0,945);
                //				ui_cmd->set.xy1(my_ui->HP[2-1][red],759-120*1,945);
                //				ui_cmd->set.xy1(my_ui->HP[3-1][red],759-120*2,945);
                //				ui_cmd->set.xy1(my_ui->HP[4-1][red],759-120*3,945);
                //				ui_cmd->set.xy1(my_ui->HP[5-1][red],759-120*4,945);
                //				ui_cmd->set.xy1(my_ui->HP[6-1][red],759-120*5,945);
                ////
                ///ui_cmd->set.xy1(my_ui->HP[7-1][red],230,1015);
                //				}
                //				else if(my_team==red){
                //							/*蓝方*/
                //				/*数值*/
                //				ui_cmd->set.int_only(my_ui->HP[1-1][blue],judge->game_robot_HP.blue_1_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[2-1][blue],judge->game_robot_HP.blue_2_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[3-1][blue],judge->game_robot_HP.blue_3_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[4-1][blue],judge->game_robot_HP.blue_4_robot_HP);
                ////
                ///ui_cmd->set.int_only(my_ui->HP[5-1][blue],judge->game_robot_HP.blue_5_robot_HP);
                //				ui_cmd->set.int_only(my_ui->HP[6-1][blue],judge->game_robot_HP.blue_7_robot_HP);
                ////
                ///ui_cmd->set.int_only(my_ui->HP[7-1][blue],judge->game_robot_HP.blue_outpost_HP);
                //				/*位置*/
                //				ui_cmd->set.xy1(my_ui->HP[1-1][blue],1140+120*0,945);
                //				ui_cmd->set.xy1(my_ui->HP[2-1][blue],1140+120*1,945);
                //				ui_cmd->set.xy1(my_ui->HP[3-1][blue],1140+120*2,945);
                //				ui_cmd->set.xy1(my_ui->HP[4-1][blue],1140+120*3,945);
                //				ui_cmd->set.xy1(my_ui->HP[5-1][blue],1140+120*4,945);
                //				ui_cmd->set.xy1(my_ui->HP[6-1][blue],1140+120*5,945);
                ////
                ///ui_cmd->set.xy1(my_ui->HP[7-1][blue],1675,1015);
                //				}
                //			}
                {  // 文本
                    if (!qwf_state->chassis.super_elec.state) {
                        if (super_elec->use)
                            ui_cmd->set.str(my_ui->mode_txt.power, "Power:Use");
                        else
                            ui_cmd->set.str(my_ui->mode_txt.power,
                                            "Power:UnUse");
                    } else
                        ui_cmd->set.str(my_ui->mode_txt.power, "Power:Err");

                    if (chassis->mode[now] == chassis_stop)
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Stop");
                    else if (chassis->mode[now] == chassis_yes)
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Yes");
                    else if (chassis->mode[now] == chassis_normal)
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Normal");
                    else if (chassis->mode[now] == chassis_follow)
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Follow");
                    else if (chassis->mode[now] == chassis_top)
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Top");
                    else if (chassis->mode[now] == chassis_fly_slope)
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Fly");
                    else
                        ui_cmd->set.str(my_ui->mode_txt.chassis, "C:Err");

                    if (communicate->head.mode.data.str.gimbal == gimbal_stop)
                        ui_cmd->set.str(my_ui->mode_txt.gimbal, "G:Stop");
                    else if (communicate->head.mode.data.str.gimbal ==
                             gimbal_yes)
                        ui_cmd->set.str(my_ui->mode_txt.gimbal, "G:Yes");
                    else if (communicate->head.mode.data.str.gimbal ==
                             gimbal_normal)
                        ui_cmd->set.str(my_ui->mode_txt.gimbal, "G:Normal");
                    else if (communicate->head.mode.data.str.gimbal ==
                             gimbal_vision)
                        ui_cmd->set.str(my_ui->mode_txt.gimbal, "G:Vision");
                    else if (communicate->head.mode.data.str.gimbal ==
                             gimbal_vision_test)
                        ui_cmd->set.str(my_ui->mode_txt.gimbal,
                                        "G:Vision_Test");
                    else
                        ui_cmd->set.str(my_ui->mode_txt.gimbal, "G:Err");

                    if (communicate->head.mode.data.str.shoot == fire_stop)
                        ui_cmd->set.str(my_ui->mode_txt.fire, "F:Stop");
                    else if (communicate->head.mode.data.str.shoot == fire_yes)
                        ui_cmd->set.str(my_ui->mode_txt.fire, "F:Yes");
                    else if (communicate->head.mode.data.str.shoot ==
                             fire_knob_stop)
                        ui_cmd->set.str(my_ui->mode_txt.fire, "F:Knob_Stop");
                    else if (communicate->head.mode.data.str.shoot == fire_once)
                        ui_cmd->set.str(my_ui->mode_txt.fire, "F:Once");
                    else if (communicate->head.mode.data.str.shoot ==
                             fire_continuous)
                        ui_cmd->set.str(my_ui->mode_txt.fire, "F:Continuos");
                    else
                        ui_cmd->set.str(my_ui->mode_txt.fire, "F:Err");

                    if (communicate->head.vision.data.str.head_ok) {
                        if (communicate->head.mode.data.str.vision ==
                            vision_mode_car) {
                            if (communicate->head.mode.data.str
                                    .use_vision_fire) {
                                if (communicate->head.vision.data.str.fire)
                                    ui_cmd->set.str(my_ui->mode_txt.vision,
                                                    "V:Car::OK");
                                else
                                    ui_cmd->set.str(my_ui->mode_txt.vision,
                                                    "V:Car::NO");
                            } else
                                ui_cmd->set.str(my_ui->mode_txt.vision,
                                                "V:Car::UnUse");

                        } else if (communicate->head.mode.data.str.vision ==
                                   vision_mode_small_flag) {
                            if (communicate->head.mode.data.str
                                    .use_vision_fire) {
                                if (communicate->head.vision.data.str.fire)
                                    ui_cmd->set.str(my_ui->mode_txt.vision,
                                                    "V:Flag_S::OK");
                                else
                                    ui_cmd->set.str(my_ui->mode_txt.vision,
                                                    "V:Flag_S::NO");
                            } else
                                ui_cmd->set.str(my_ui->mode_txt.vision,
                                                "V:Flag_S::UnUse");

                        } else if (communicate->head.mode.data.str.vision ==
                                   vision_mode_big_flag) {
                            if (communicate->head.mode.data.str
                                    .use_vision_fire) {
                                if (communicate->head.vision.data.str.fire)
                                    ui_cmd->set.str(my_ui->mode_txt.vision,
                                                    "V:Flag_B::OK");
                                else
                                    ui_cmd->set.str(my_ui->mode_txt.vision,
                                                    "V:Flag_B::NO");
                            } else
                                ui_cmd->set.str(my_ui->mode_txt.vision,
                                                "V:Flag_S::UnUse");
                        } else
                            ui_cmd->set.str(my_ui->mode_txt.vision, "V:Err");
                    } else
                        ui_cmd->set.str(my_ui->mode_txt.vision, "V:Head_Lose");
                }
                {  // 可修改文件
                    //				if(rc_key_last.e==1&&ctrl->KM[now].key.e==1){
                    //					ui_cmd->set.visible(my_ui->change.w_top.text,1);
                    //					ui_cmd->set.visible(my_ui->change.w_top.num,1);
                    //					ui_cmd->set.int_only(my_ui->change.w_top.num,chassia_top_w_now);
                    //					if(Use_Change_Top)
                    //						ui_cmd->set.str(my_ui->change.w_top.text,"W_Top:Change");
                    //					else
                    //						ui_cmd->set.str(my_ui->change.w_top.text,"W_Top:Normal");
                    //				}
                    //				else{
                    //					ui_cmd->set.visible(my_ui->change.w_top.text,0);
                    //					ui_cmd->set.visible(my_ui->change.w_top.num,0);
                    //				}
                    //
                    //				if(rc_key_last.q==1&&ctrl->KM[now].key.q==1){
                    //					ui_cmd->set.visible(my_ui->change.v_fire.text,1);
                    //					ui_cmd->set.visible(my_ui->change.v_fire.num,1);
                    //					ui_cmd->set.int_only(my_ui->change.v_fire.num,((Gimbal_Mode_Communicate_Struct_Type*)(communicate->head.mode->Data))->fire_max_i_want);
                    //					if(((Gimbal_Mode_Communicate_Struct_Type*)(communicate->head.mode->Data))->Use_Fire_Loop)
                    //						ui_cmd->set.str(my_ui->change.v_fire.text,"V_Fire:Loop");
                    //					else
                    //						ui_cmd->set.str(my_ui->change.v_fire.text,"V_Fire:Normal");
                    //				}
                    //				else{
                    //					ui_cmd->set.visible(my_ui->change.v_fire.text,0);
                    //					ui_cmd->set.visible(my_ui->change.v_fire.num,0);
                    //				}
                }
                JLUI_10HzTick();
            } break;
        }
        vTaskDelay(100);
    }
}
